use lazy_static::lazy_static;
use crc::Crc;
use crate::util;

lazy_static! {
    static ref MODBUS_CRC : Crc<u16> = crc::Crc::<u16>::new(&crc::CRC_16_MODBUS);
}

pub fn modbus_check(u: &[u8; 6]) -> [u8; 2] {
    let sum = MODBUS_CRC.checksum(u);
    util::u16_to_u8_slice_reverse(sum)
}

pub fn modbus_check_slice(u: &[u8]) -> [u8; 2] {
    let sum = MODBUS_CRC.checksum(u);
    util::u16_to_u8_slice_reverse(sum)
}

pub fn modbus_check_result(result: &[u8]) -> bool {
    if result.len() < 3 || result.len() != result[2] as usize + 5 { return false; }
    let check_index = result.len() - 2;
    modbus_check_slice(&result[..check_index]).eq(&result[check_index..check_index + 2])
}

#[cfg(test)]
mod tests {
    use crate::modbus::mcrc;

    #[test]
    fn test() {
        let checked = mcrc::modbus_check(&[0x01, 0x03, 0x00, 0x00, 0x00, 0x03]);//> 0xCB05 -> [05,CB]
        println!("{:?}", checked);
        for x in checked {
            println!("{:x}", x);
        }

        let c = mcrc::modbus_check_slice(&[0x01, 0x03, 0x02, 0x00, 0x01]);
        let b = mcrc::modbus_check_result(&[0x01, 0x03, 0x02, 0x00, 0x01, c[0], c[1]]);
        println!("{}", b);
    }

    #[test]
    fn test2() {
        println!("{:?}", mcrc::modbus_check_slice(&[0x01, 0x03, 0x04, 0x02, 0x96, 0xff, 0x9b]));
    }
}